package locks.solve;

import locks.entity.Account;
import locks.entity.DollarAmount;
import locks.exception.InsufficientFundsException;

/**
 * 通过顺序 避免死锁
 */
public class DynamicSequenceDeadLockSolve {

    //加时赛锁
    private static final Object tieLock=new Object();

    public static void transferMoney(Account fromAccount,
                                     Account toAccount,
                                     DollarAmount amount)
            throws InsufficientFundsException {
        class Helper {
            public void transfer() throws InsufficientFundsException {
                //账户余额大于O
                if (fromAccount.getBalance().compareTo(amount) < 0)
                    throw new InsufficientFundsException();
                else {
                    //转账
                    fromAccount.debit(amount);
                    toAccount.credit(amount);
                }
            }
        }
        int fromHash = System.identityHashCode(fromAccount);
        int toHash = System.identityHashCode(toAccount);
        if(fromHash<toHash){
            synchronized (fromAccount){
                synchronized (toAccount){
                    new Helper().transfer();
                }
            }
        }else if(fromHash>toHash){
            synchronized (toAccount){
                synchronized (fromAccount){
                    new Helper().transfer();
                }
            }
        }else{
            //两个对象hash值相等 那么有可能再次引入死锁，所以加入更高级别的锁来解决
            synchronized (tieLock){
                synchronized (fromAccount){
                    synchronized (toAccount){
                        new Helper().transfer();
                    }
                }
            }
        }
    }

}
